import {
  isNull,
  PagedList,
  PageParams,
} from "mmb";
import * as product_grouppb from "../grpc-client/service/product_group_pb";
import {
  getBgsProductGroupOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {ProductGroup} from "./declareTypes"

/****************************************************************************************/
/*                                   product_group entity                               */
/****************************************************************************************/


const productGroupPbToObject = (pb: product_grouppb.ProductGroupEntity): ProductGroup => {
  return {
    productGroupId: `${pb.getId()}`,
    brandId: `${pb.getBrandId()}`,
    sortNo: pb.getSortNo(),
    name: pb.getName(),
    productCount: pb.getProductCount(),
  };
};

/****************************************************************************************/
/*                                   product_group cmd                                  */
/****************************************************************************************/

export interface UpsertProductGroupParams {
  brandId: string;
  name: string;
}

export const upsertProductGroup = async ({
  brandId,
  name,
}: UpsertProductGroupParams): Promise<ProductGroup> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.UpsertProductGroupRequest();

  req.setBrandId(Number(brandId));
  req.setName(name);

  return new Promise((resolve, reject) => {
    cl.upsertProductGroup(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(productGroupPbToObject(res.getProductGroup()!));
    });
  });
};

export interface UpdateProductGroupNameParams {
  productGroupId: string;
  name: string;
}

export const updateProductGroupName = async ({
  productGroupId,
  name,
}: UpdateProductGroupNameParams): Promise<ProductGroup> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.UpdateProductGroupNameRequest();

  req.setId(Number(productGroupId));
  req.setName(name);

  return new Promise((resolve, reject) => {
    cl.updateProductGroupName(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(productGroupPbToObject(res.getProductGroup()!));
    });
  });
};

export const reorderProductGroups = async (productGroupIds: string[]): Promise<Number> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.ReorderProductGroupsRequest();

  req.setIdsList(productGroupIds.map(id => Number(id)));

  return new Promise((resolve, reject) => {
    cl.reorderProductGroups(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(res.getTotal());
    });
  });
};


export interface RemoveProductGroupParams {
  productGroupId: string;
}

export const removeProductGroup = async ({
  productGroupId,
}: RemoveProductGroupParams): Promise<ProductGroup> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.RemoveProductGroupRequest();

  req.setId(Number(productGroupId));
  
  return new Promise((resolve, reject) => {
    cl.removeProductGroup(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(productGroupPbToObject(res.getProductGroup()!));
    });
  });
};

/****************************************************************************************/
/*                                   product_group query                              */
/****************************************************************************************/

export const getProductGroup = async (
  productGroupId: string
): Promise<ProductGroup> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.GetProductGroupRequest();

  req.setId(Number(productGroupId));

  return new Promise((resolve, reject) => {
    cl.getProductGroup(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(productGroupPbToObject(res.getProductGroup()!));
    });
  });
};

export const listNormalProductGroupsByBrandID = async (
  brandId: string,
  pager: PageParams
): Promise<PagedList<ProductGroup>> => {
  const cl = getBgsProductGroupOpSafely();
  const req = new product_grouppb.ListNormalProductGroupsByBrandIDRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setBrandId(Number(brandId));

  return new Promise((resolve, reject) => {
    cl.listNormalProductGroupsByBrandID(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      const ret: PagedList<ProductGroup> = {
        total: 0,
        items: [],
      };
      ret.total = res.getTotal();
      ret.items = res.getProductGroupsList().map((u) => productGroupPbToObject(u));
      resolve(ret);
    });
  });
};


